﻿using System;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Reflection;
using System.Xml;

namespace Miao
{
    /// <summary>
    /// Xml继承
    /// </summary>
    public static class XmlInheritance
    {
        private class XmlInheritanceNode
        {
            public XmlNode xmlNode;
            /// <summary>
            /// 已解析完成的xml节点
            /// </summary>
            public XmlNode resolvedXmlNode;

            public ModContentPack mod;

            public XmlInheritanceNode parent;

            public List<XmlInheritanceNode> children = new List<XmlInheritanceNode>();
        }
        /// <summary>
        /// 已解析具有继承关系的节点
        /// </summary>
        private static Dictionary<XmlNode, XmlInheritanceNode> resolvedNodeDict;
        /// <summary>
        /// 包含可能存在的父子关系中的未解析节点
        /// </summary>
        private static List<XmlInheritanceNode> unresolvedNodes;

        private static Dictionary<string, List<XmlInheritanceNode>> nodesByName;
        /// <summary>
        /// 允许重复的节点字段名，这项我们先不需要
        /// </summary>
        //public static HashSet<string> allowDuplicateNodesFieldNames;

        private const string NameAttributeName = "Name";

        private const string ParentNameAttributeName = "ParentName";

        private const string InheritAttributeName = "Inherit";

        private static HashSet<string> tempUsedNodeNames;

        static XmlInheritance()
        {
            resolvedNodeDict = new Dictionary<XmlNode, XmlInheritanceNode>();
            unresolvedNodes = new List<XmlInheritanceNode>();
            nodesByName = new Dictionary<string, List<XmlInheritanceNode>>();
            tempUsedNodeNames = new HashSet<string>();
        }

        public static void TryRegisterAllFrom(LoadableXmlAsset xmlAsset, ModContentPack mod)
        {
            if (xmlAsset.xmlDoc == null)
            {
                return;
            }
            foreach (XmlNode childNode in xmlAsset.xmlDoc.DocumentElement.ChildNodes)
            {
                if (childNode.NodeType == XmlNodeType.Element)
                {
                    TryRegister(childNode, mod);
                }
            }
        }

        public static void TryRegister(XmlNode node, ModContentPack mod)
        {
            XmlAttribute xmlAttributeName = node.Attributes["Name"];
            XmlAttribute xmlAttributeParentName = node.Attributes["ParentName"];
            if (xmlAttributeName == null && xmlAttributeParentName == null)
            {
                return;
            }
            List<XmlInheritanceNode> value = null;
            if (xmlAttributeName != null && nodesByName.TryGetValue(xmlAttributeName.Value, out value))
            {
                for (int i = 0; i < value.Count; i++)
                {
                    if (value[i].mod == mod)
                    {
                        if (mod == null)
                        {
                            Log.Error("XML error: Could not register node named \"" + xmlAttributeName.Value + "\" because this name is already used.");
                            return;
                        }
                        Log.Error("XML error: Could not register node named \"" + xmlAttributeName.Value + "\" in mod " + mod.ToString() + " because this name is already used in this mod.");
                        return;
                    }
                }
            }
            XmlInheritanceNode xmlInheritanceNode = new XmlInheritanceNode();
            xmlInheritanceNode.xmlNode = node;
            xmlInheritanceNode.mod = mod;
            unresolvedNodes.Add(xmlInheritanceNode);
            if (xmlAttributeName != null)
            {
                if (value != null)
                {
                    value.Add(xmlInheritanceNode);
                    return;
                }
                //就是个初始化添加的系统
                value = new List<XmlInheritanceNode>();
                value.Add(xmlInheritanceNode);
                nodesByName.Add(xmlAttributeName.Value, value);
            }
        }

        public static void Resolve()
        {
            ResolveParentsAndChildNodesLinks();
            ResolveXmlNodes();
        }
        /// <summary>
        /// 获取进行父子集关系后的xmlNode
        /// </summary>
        /// <param name="originalNode"></param>
        /// <returns></returns>
        public static XmlNode GetResolvedNodeFor(XmlNode originalNode)
        {
            if (originalNode.Attributes["ParentName"] != null)
            {
                if (resolvedNodeDict.TryGetValue(originalNode, out var value))
                {
                    return value.resolvedXmlNode;
                }
                if (unresolvedNodes.Any((XmlInheritanceNode x) => x.xmlNode == originalNode))
                {
                    Log.Error("XML error: XML node \"" + originalNode.Name + "\" has not been resolved yet. There's probably a Resolve() call missing somewhere.");
                }
                else
                {
                    Log.Error("XML error: Tried to get resolved node for node \"" + originalNode.Name + "\" which uses a ParentName attribute, but it is not in a resolved nodes collection, which means that it was never registered or there was an error while resolving it.");
                }
            }
            return originalNode;
        }

        public static void Clear()
        {
            resolvedNodeDict.Clear();
            unresolvedNodes.Clear();
            nodesByName.Clear();
        }
        /// <summary>
        /// 绑定父类和子类节点集关系
        /// </summary>
        private static void ResolveParentsAndChildNodesLinks()
        {
            for (int i = 0; i < unresolvedNodes.Count; i++)
            {
                XmlAttribute xmlAttribute = unresolvedNodes[i].xmlNode.Attributes["ParentName"];
                if (xmlAttribute != null)
                {
                    unresolvedNodes[i].parent = GetBestParentFor(unresolvedNodes[i], xmlAttribute.Value);
                    if (unresolvedNodes[i].parent != null)
                    {
                        unresolvedNodes[i].parent.children.Add(unresolvedNodes[i]);
                    }
                }
            }
        }
        /// <summary>
        /// 绑定父类和子类xml关系
        /// </summary>
        private static void ResolveXmlNodes()
        {
            //获取根目录下顶级父类
            IEnumerable<XmlInheritanceNode> topList = unresolvedNodes.Where((XmlInheritanceNode x) => x.parent == null);
            //IEnumerable<XmlInheritanceNode> topList =  unresolvedNodes.Where((XmlInheritanceNode x) => x.parent == null || x.parent.resolvedXmlNode != null).ToList();
            foreach (XmlInheritanceNode inheritanceNode in topList)
            {
                ResolveXmlNodesRecursively(inheritanceNode);
            }

           
            for (int j = 0; j < unresolvedNodes.Count; j++)
            {
                if (unresolvedNodes[j].resolvedXmlNode == null)
                {
                    Log.Error("XML error: Cyclic inheritance hierarchy detected for node \"" + unresolvedNodes[j].xmlNode.Name + "\". Full node: " + unresolvedNodes[j].xmlNode.OuterXml);
                }
                else
                {
                    resolvedNodeDict.Add(unresolvedNodes[j].xmlNode, unresolvedNodes[j]);
                }
            }
            unresolvedNodes.Clear();
        }
        /// <summary>
        /// 递归解析Xml节点
        /// </summary>
        /// <param name="inheritanceNode"></param>
        private static void ResolveXmlNodesRecursively(XmlInheritanceNode inheritanceNode)
        {
            if (inheritanceNode.resolvedXmlNode != null)
            {
                Log.Error("XML error: Cyclic inheritance hierarchy detected for node \"" + inheritanceNode.xmlNode.Name + "\". Full node: " + inheritanceNode.xmlNode.OuterXml);
                return;
            }

            ResolveXmlNodeFor(inheritanceNode);

            for (int i = 0; i < inheritanceNode.children.Count; i++)
            {
                ResolveXmlNodesRecursively(inheritanceNode.children[i]);
            }
        }
        /// <summary>
        /// 获取父类
        /// </summary>
        /// <param name="node"></param>
        /// <param name="parentName"></param>
        /// <returns></returns>
        private static XmlInheritanceNode GetBestParentFor(XmlInheritanceNode node, string parentName)
        {
            XmlInheritanceNode xmlInheritanceNode = null;
            if (nodesByName.TryGetValue(parentName, out var value))
            {
                if (node.mod == null)
                {
                    for (int i = 0; i < value.Count; i++)
                    {
                        if (value[i].mod == null)
                        {
                            xmlInheritanceNode = value[i];
                            break;
                        }
                    }
                    if (xmlInheritanceNode == null)
                    {
                        for (int j = 0; j < value.Count; j++)
                        {
                            if (xmlInheritanceNode == null || value[j].mod.LoadOrder < xmlInheritanceNode.mod.LoadOrder)
                            {
                                xmlInheritanceNode = value[j];
                            }
                        }
                    }
                }
                else
                {
                    for (int k = 0; k < value.Count; k++)
                    {
                        if (value[k].mod != null && value[k].mod.LoadOrder <= node.mod.LoadOrder && (xmlInheritanceNode == null || value[k].mod.LoadOrder > xmlInheritanceNode.mod.LoadOrder))
                        {
                            xmlInheritanceNode = value[k];
                        }
                    }
                    if (xmlInheritanceNode == null)
                    {
                        for (int l = 0; l < value.Count; l++)
                        {
                            if (value[l].mod == null)
                            {
                                xmlInheritanceNode = value[l];
                                break;
                            }
                        }
                    }
                }
            }
            if (xmlInheritanceNode == null)
            {
                Log.Error("XML error: Could not find parent node named \"" + parentName + "\" for node \"" + node.xmlNode.Name + "\". Full node: " + node.xmlNode.OuterXml);
                return null;
            }
            return xmlInheritanceNode;
        }
        /// <summary>
        /// 解析XmlNode从根条目
        /// </summary>
        /// <param name="node"></param>
        private static void ResolveXmlNodeFor(XmlInheritanceNode node)
        {
            if (node.parent == null)
            {
                node.resolvedXmlNode = node.xmlNode;
                return;
            }
            if (node.parent.resolvedXmlNode == null)
            {
                Log.Error("XML error: Internal error. Tried to resolve node whose parent has not been resolved yet. This means that this method was called in incorrect order.");
                node.resolvedXmlNode = node.xmlNode;
                return;
            }
            CheckForDuplicateNodes(node.xmlNode, node.xmlNode);
            //克隆父类的节点脚本
            XmlNode parentXmlNode = node.parent.resolvedXmlNode.CloneNode(deep: true);
            RecursiveNodeCopyOverwriteElements(node.xmlNode, parentXmlNode);
            node.resolvedXmlNode = parentXmlNode;
        }
        /// <summary>
        /// 递归节点复制覆盖元素
        /// </summary>
        /// <param name="child"></param>
        /// <param name="parent"></param>
        private static void RecursiveNodeCopyOverwriteElements(XmlNode child, XmlNode parent)
        {
            //var testchild = child.Attributes["Name"].Value;
            //var testRoot = parent.Attributes["Name"].Value;
            XmlAttribute xmlAttribute = child.Attributes["Inherit"];//是否允许继承
            if (xmlAttribute != null && xmlAttribute.Value.ToLower() == "false")
            {
                while (parent.HasChildNodes)
                {
                    parent.RemoveChild(parent.FirstChild);
                }
                foreach (XmlNode item in child)
                {
                    XmlNode newChild = parent.OwnerDocument.ImportNode(item, deep: true);
                    parent.AppendChild(newChild);
                }
                foreach (XmlAttribute attribute in child.Attributes)
                {
                    if (!(attribute.Name == "Inherit"))
                    {
                        XmlAttribute xmlAttribute3 = parent.OwnerDocument.CreateAttribute(attribute.Name);
                        xmlAttribute3.Value = attribute.Value;
                        parent.Attributes.Append(xmlAttribute3);
                    }
                }
                return;
            }
            parent.Attributes.RemoveAll();
            XmlAttributeCollection attributes = child.Attributes;
            for (int i = 0; i < attributes.Count; i++)
            {
                XmlAttribute node2 = (XmlAttribute)parent.OwnerDocument.ImportNode(attributes[i], deep: true);
                parent.Attributes.Append(node2);
            }
            List<XmlElement> childList = new List<XmlElement>();
            XmlNode xmlNode = null;
            foreach (XmlNode childNode in child)
            {
                if (childNode.NodeType == XmlNodeType.Text)
                {
                    xmlNode = childNode;
                }
                else if (childNode.NodeType == XmlNodeType.Element)
                {
                    childList.Add((XmlElement)childNode);
                }
            }
            if (xmlNode != null)
            {
                for (int num = parent.ChildNodes.Count - 1; num >= 0; num--)//可能是什么保护措施吧，= XmlNodeType.Text会是1
                {
                    XmlNode xmlNode3 = parent.ChildNodes[num];
                    if (xmlNode3.NodeType != XmlNodeType.Attribute)
                    {
                        parent.RemoveChild(xmlNode3);
                    }
                }

                XmlNode newChild2 = parent.OwnerDocument.ImportNode(xmlNode, deep: true);
                parent.AppendChild(newChild2);
                return;
            }
            if (!childList.Any())
            {
                bool flag = false;
                foreach (XmlNode childNode in parent.ChildNodes)
                {
                    if (childNode.NodeType == XmlNodeType.Element)
                    {
                        flag = true;
                        break;
                    }
                }
                if (flag)
                {
                    return;
                }
                foreach (XmlNode childNode2 in parent.ChildNodes)
                {
                    if (childNode2.NodeType != XmlNodeType.Attribute)
                    {
                        parent.RemoveChild(childNode2);
                    }
                }
                return;
            }
            for (int j = 0; j < childList.Count; j++)
            {
                XmlElement childXmlElement = childList[j];
                if (IsListElement(childXmlElement))
                {
                    XmlNode newChild3 = parent.OwnerDocument.ImportNode(childXmlElement, deep: true);
                    parent.AppendChild(newChild3);
                    continue;
                }
                XmlElement parentSubXmlElement = parent[childXmlElement.Name];//去查找父类的xml是否拥有该数据。
                if (parentSubXmlElement != null)//有这个名字就继续递归
                {
                    RecursiveNodeCopyOverwriteElements(childXmlElement, parentSubXmlElement);
                    continue;
                }
                {
                    XmlNode parentNeedChild = parent.OwnerDocument.ImportNode(childXmlElement, deep: true);//没有的情况下将子类套入父类
                    parent.AppendChild(parentNeedChild);
                }
            }
        }
        //检查是否有重复节点
        private static void CheckForDuplicateNodes(XmlNode node, XmlNode root)
        {
            tempUsedNodeNames.Clear();
            foreach (XmlNode childNode in node.ChildNodes)
            {
                if (childNode.NodeType == XmlNodeType.Element && !IsListElement(childNode))
                {
                    if (tempUsedNodeNames.Contains(childNode.Name))
                    {
                        Log.Error("XML error: Duplicate XML node name " + childNode.Name + " in this XML block: " + node.OuterXml + ((node != root) ? ("\n\nRoot node: " + root.OuterXml) : ""));
                    }
                    else
                    {
                        tempUsedNodeNames.Add(childNode.Name);
                    }
                }
            }
            tempUsedNodeNames.Clear();
            foreach (XmlNode childNode2 in node.ChildNodes)
            {
                if (childNode2.NodeType == XmlNodeType.Element)
                {
                    CheckForDuplicateNodes(childNode2, root);
                }
            }
        }

        private static bool IsListElement(XmlNode node)
        {
            if (!(node.Name == "li"))
            {
                return false;
            }
            return true;
        }
    }
}
